package com.shu.logsearch.jsch.util;

import cn.hutool.core.io.FileUtil;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.shu.logsearch.jsch.core.Xshell;
import com.shu.logsearch.util.CloseUtil;
import com.shu.logsearch.util.MyFileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.Vector;

/**
 * 基于jsch的远程服务器ftp连接工具
 *
 * @author Tree Cai
 * @date 2019/7/2
 */
@Component
public class FtpUtil {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private Xshell xshell;

    /**
     * 下载文件
     *
     * @param remoteFilePath 远程服务器的文件路径
     * @param localFilePath  本地的文件路径
     * @return
     */
    public File downFile(String remoteFilePath, String localFilePath) {
        File localFile = null;
        OutputStream output = null;
        ChannelSftp sftp = xshell.getSftp();
        logger.info(String.format("--->开始下载文件>>>>>\n从【%s】到【%s】", remoteFilePath, localFilePath));
        // 远端目录确定以 / 作为目录格式
        String rFileSeparator = "/";
        int rDirNameSepIndex = remoteFilePath.lastIndexOf(rFileSeparator) + 1;
        String remoteDir = remoteFilePath.substring(0, rDirNameSepIndex);
        String remoteFileName = remoteFilePath.substring(rDirNameSepIndex);
        if (localFilePath.endsWith(File.separator)) {
            localFilePath = localFilePath + (localFilePath.endsWith(File.separator) ? remoteFileName : "/" + remoteFileName);
        }

        try {
            localFile = new File(localFilePath);
            if (localFile.exists()) {
                localFile.delete();
            }
            localFile.createNewFile();
            sftp.cd(remoteDir);
            sftp.get(remoteFileName, output = new FileOutputStream(localFile));
        } catch (SftpException e) {
            logger.error("ftp下载文件失败", e);
            e.printStackTrace();
        } catch (IOException e) {
            logger.error("本地目录异常，请检查:" + localFilePath, e);
            e.printStackTrace();
        } finally {
            CloseUtil.close(output, "localFileOutput");
        }
        return localFile;
    }


    /**
     * 将远程服务器remoteDirPath中的所有文件下载到本地的localDirPath中
     *
     * @param remoteDirPath 远程服务器的文件夹路径
     * @param localDirPath  本地的文件夹路径
     * @return
     */
    public boolean downAllFile(String remoteDirPath, String localDirPath) {
        ChannelSftp sftp = xshell.getSftp();
        try {
            Vector<ChannelSftp.LsEntry> fileList = sftp.ls(remoteDirPath);
            for (ChannelSftp.LsEntry file : fileList) {
                OutputStream output = null;
                try {
                    String fileName = file.getFilename();
                    if (fileName.equals(".") || fileName.equals(".."))
                        continue;
                    File localFile = FileUtil.touch(localDirPath + fileName);
                    output = new FileOutputStream(localFile);
                    sftp.cd(remoteDirPath);
                    sftp.get(fileName, output, new FtpProgressMonitor());
                    System.out.println(localFile.setLastModified(file.getAttrs().getMTime()));
                } catch (SftpException e) {
                    logger.error("ftp下载文件失败，请检查：" + remoteDirPath + file.getFilename(), e);
                    e.printStackTrace();
                    continue;
                } catch (FileNotFoundException e) {
                    logger.error("本地目录异常，请检查:" + localDirPath, e);
                    e.printStackTrace();
                    continue;
                }  finally {
                    CloseUtil.close(output, "", false);
                }
            }
            return true;
        } catch (SftpException e) {
            logger.error("ftp获取文件目录失败", e);
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 执行单句命令
     * @param command
     * @param resultEncoding
     * @return
     */
    public String execCommand(String command, String resultEncoding) throws IOException, JSchException {
        return xshell.execCommand(command, resultEncoding);
    }

    /**
     * 远程服务器是否存在该文件
     *
     * @param remoteFilePath
     * @return
     */
    public boolean existRemoteFile(String remoteFilePath) {
        try {
            xshell.getSftp().get(remoteFilePath);
            return true;
        } catch (SftpException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 远程服务器是否存在该路径
     *
     * @param remoteDir
     * @return
     */
    public boolean existRemoteDir(String remoteDir) {
        try {
            xshell.getSftp().cd(remoteDir);
            return true;
        } catch (SftpException e) {
            e.printStackTrace();
            return false;
        }
    }
}
